package com.zzzy.doc.service.mydoc;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.zzzy.common.exception.WarningException;
import com.zzzy.common.util.AssertUtil;
import com.zzzy.common.util.CglibBeanCopierUtil;
import com.zzzy.common.util.FileUtil;
import com.zzzy.common.util.MyBatisUtils;
import com.zzzy.common.vo.PageResult;
import com.zzzy.doc.common.enums.DocStatusEnum;
import com.zzzy.doc.common.enums.UrgencyEnum;
import com.zzzy.doc.dao.entity.DocFile;
import com.zzzy.doc.dao.entity.Document;
import com.zzzy.doc.dto.DocumentStatusCountDto;
import com.zzzy.doc.service.DocService;
import com.zzzy.doc.vo.document.DocInfoRes;
import com.zzzy.doc.vo.document.my.DocUpdateReq;
import com.zzzy.doc.vo.document.my.MyDocButtonRes;
import com.zzzy.doc.vo.document.my.MyDocPageReq;
import com.zzzy.doc.vo.document.my.MyDocStatisticsRes;
import com.zzzy.framework.common.util.SecurityUtils;
import com.zzzy.framework.common.util.SortFieldUtil;
import com.zzzy.framework.dto.LoginUser;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class MyDocService extends DocService {

    public PageResult<Document> getMyDocPage(MyDocPageReq queryReq) {
        IPage<Document> mpPage = MyBatisUtils.buildPage(queryReq, SortFieldUtil.getSortingFields(Document.class, queryReq.getOrderField(), queryReq.getOrderRule()));
        mpPage = baseMapper.selectMyDocumentPage(mpPage, queryReq, SecurityUtils.getLoginUser().getId());
        Map<Object, String> urgencyMap = dictService.getDictDataMap(UrgencyEnum.class);
        mpPage.getRecords().forEach(doc -> doc.setUrgencyDescription(urgencyMap.get(doc.getUrgency())));
        return new PageResult<>(mpPage);
    }


    public void updateById(DocUpdateReq updateReq) {
        Document document = getDocByIdForUpdate(updateReq.getId());
        if (!DocStatusEnum.DRAFT.getValue().equals(document.getStatus())
                && !DocStatusEnum.AUDIT.getValue().equals(document.getStatus())
                && !DocStatusEnum.JOINT_SIGN.getValue().equals(document.getStatus())
                && !DocStatusEnum.LEADER_SIGN.getValue().equals(document.getStatus())
                && !DocStatusEnum.RED_SHEET_TEMPLATE.getValue().equals(document.getStatus())){
            throw new WarningException("公文状态错误，无法修改");
        }
        CglibBeanCopierUtil.copy(updateReq, document);
        document.setUpdateTime(LocalDateTime.now());
        baseMapper.updateById(document);
    }

    @Transactional
    public void deleteById(Long id) {
        Document document = getDocByIdForUpdate(id);
        AssertUtil.isEquals(DocStatusEnum.DRAFT.getValue(), document.getStatus(), "只有拟稿中公文可删除,其他状态只能作废");
        baseMapper.deleteById(id);
        //删除文件信息
        docFileService.remove(new LambdaQueryWrapper<DocFile>().eq(DocFile::getDocId, id));
    }

    public MyDocButtonRes getButton(Long id) {
        DocInfoRes docInfoRes = getDocInfo(id);
        boolean isWord = Objects.isNull(docInfoRes.getPdfFileBlob());

        boolean isArchived = DocStatusEnum.ARCHIVED.getValue().equals(docInfoRes.getStatus());
        boolean isCancel = DocStatusEnum.CANCEL.getValue().equals(docInfoRes.getStatus());
        MyDocButtonRes buttonRes = new MyDocButtonRes();
        buttonRes.setOpenFinalPdf(!isWord);
        if (isArchived || isCancel){
            return buttonRes;
        }
        LoginUser loginUser = SecurityUtils.getLoginUser();
        //是否当前可操作人
        boolean isCurrentOperator = docInfoRes.getOperatorId().equals(loginUser.getId());
        //是否创建人
        boolean isCreateUser = docInfoRes.getUserId().equals(loginUser.getId());
        boolean isDraft = DocStatusEnum.DRAFT.getValue().equals(docInfoRes.getStatus());
        //套红
        boolean isProofreadFormat = DocStatusEnum.RED_SHEET_TEMPLATE.getValue().equals(docInfoRes.getStatus());
        //分发
        boolean isDistribute = DocStatusEnum.DISTRIBUTE.getValue().equals(docInfoRes.getStatus());
        boolean isComplete = DocStatusEnum.COMPLETE.getValue().equals(docInfoRes.getStatus());
        buttonRes.setEdit(isCurrentOperator && isWord);
        //是创建人且为当前处理人,状态为拟稿中 则可删除
        buttonRes.setDelete(isCreateUser && isCurrentOperator && isDraft);
        buttonRes.setCancel(isCreateUser && isCurrentOperator && !isDraft && !isComplete);
        buttonRes.setAddAttachment(true);
        buttonRes.setDeleteAttachment(true);
        buttonRes.setCompareClick(isCurrentOperator && isProofreadFormat);
        buttonRes.setApply(isCreateUser && isCurrentOperator && !isDraft && !isProofreadFormat && !isDistribute && !isComplete);
        buttonRes.setNext(isCreateUser && isCurrentOperator);
        return buttonRes;
    }

    @Override
    @Transactional
    public void updateApprovalWord(Long id, byte[] byteArray) {
        AssertUtil.isTrue(getButton(id).isEdit(), "用户当前无法修改此公文");
        super.updateApprovalWord(id, byteArray);
    }

    @Override
    @Transactional
    public void updateMainWord(Long id, byte[] byteArray, Integer revisionCount) {
        AssertUtil.isTrue(FileUtil.getFileType(byteArray).equals(FileUtil.DOCX), "请上传docx格式的word文件");
        AssertUtil.isTrue(getButton(id).isEdit(), "用户当前无法修改此公文");
        super.updateMainWord(id, byteArray, revisionCount);
    }

    @Override
    @Transactional
    public void updateFinalPdf(Long id, byte[] byteArray) {
        Document document = getDocByIdForQuery(id);
        Long loginUserId = SecurityUtils.getLoginUser().getId();
        AssertUtil.isTrue(loginUserId.equals(document.getOperatorId()) && DocStatusEnum.SIGN.getValue().equals(document.getStatus())
                , "用户当前无法签证此公文正文");
        super.updateFinalPdf(id, byteArray);
    }

    public void cancel(Long id) {
        Document document = getDocByIdForUpdate(id);
        if (DocStatusEnum.DRAFT.getValue().equals(document.getStatus())
                || DocStatusEnum.ARCHIVED.getValue().equals(document.getStatus())
                || DocStatusEnum.CANCEL.getValue().equals(document.getStatus())){
            throw new WarningException("公文状态错误");
        }
        document.setStatus(DocStatusEnum.CANCEL.getValue());
        document.setUpdateTime(LocalDateTime.now());
        baseMapper.updateById(document);

    }

    /**
     * 更新 正文文本
     */
    public void updateMainText(Long id, String documentText) {
        Document document = getDocByIdForUpdate(id);
        document.setDocText(documentText);
        baseMapper.updateById(document);
    }
    /**
     * 更新 正文缩略图
     */
    public void updateMainImage(Long id, byte[] fileBytes) {
        Document document = getDocByIdForUpdate(id);
        document.setDocThumbnailBlob(fileBytes);
        baseMapper.updateById(document);
    }

    public MyDocStatisticsRes getStatistics() {
        Long userId = SecurityUtils.getLoginUser().getId();
        List<DocumentStatusCountDto> statusCountList = baseMapper.selectMyDocumentStatusCountList(userId);
        Map<String, Long> statusCountMap = statusCountList.stream().collect(Collectors.toMap(DocumentStatusCountDto::getStatus, DocumentStatusCountDto::getCounts));
        MyDocStatisticsRes statisticsRes = new MyDocStatisticsRes();
        statisticsRes.setDraftCount(statusCountMap.get(DocStatusEnum.DRAFT.getValue()));
        statisticsRes.setAuditCount(statusCountMap.get(DocStatusEnum.AUDIT.getValue()));
        statisticsRes.setJointSignCount(statusCountMap.get(DocStatusEnum.JOINT_SIGN.getValue()));
        statisticsRes.setLeaderSignCount(statusCountMap.get(DocStatusEnum.LEADER_SIGN.getValue()));
        statisticsRes.setRedSheetTemplateCount(statusCountMap.get(DocStatusEnum.RED_SHEET_TEMPLATE.getValue()));
        statisticsRes.setSignCount(statusCountMap.get(DocStatusEnum.SIGN.getValue()));
        statisticsRes.setDistributeCount(statusCountMap.get(DocStatusEnum.DISTRIBUTE.getValue()));
        statisticsRes.setCompleteCount(statusCountMap.get(DocStatusEnum.COMPLETE.getValue()));
        statisticsRes.setArchivedCount(statusCountMap.get(DocStatusEnum.ARCHIVED.getValue()));
        statisticsRes.setCancelCount(statusCountMap.get(DocStatusEnum.CANCEL.getValue()));
        return statisticsRes;
    }
}
